package org.codehaus.activemq.message.util;

import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

class DataContainer
{
  private CopyOnWriteArrayList dataBlocks = new CopyOnWriteArrayList();
  private FileDataBlock writeBlock;
  private FileDataBlock readBlock;
  private File dir;
  private long length;
  private int size;
  private String name;
  private int maxBlockSize;
  private int sequence;
  private static final String SUFFIX = ".fdb";
  private static final Log log = LogFactory.getLog(DataContainer.class);

  DataContainer(File dir, String name, int maxBlockSize)
    throws IOException
  {
    this.dir = dir;
    this.name = name;
    this.maxBlockSize = maxBlockSize;
  }

  void deleteAll()
  {
    FileFilter filter = new FileFilter() {
      public boolean accept(File file) {
        return (file.getName().endsWith(".fdb")) && (file.getName().startsWith(DataContainer.this.name));
      }
    };
    File[] files = this.dir.listFiles(filter);
    if (files != null)
      for (int i = 0; i < files.length; i++)
        files[i].delete();
  }

  public synchronized boolean isEmpty()
  {
    return this.size == 0;
  }

  public long length()
  {
    return this.length;
  }

  public int size()
  {
    return this.size;
  }

  public synchronized void write(byte[] data)
    throws IOException
  {
    if (this.writeBlock == null) {
      this.writeBlock = createDataBlock(this.sequence++);
      this.dataBlocks.add(this.writeBlock);
      this.readBlock = this.writeBlock;
    }
    else if (!this.writeBlock.isEnoughSpace(data)) {
      this.writeBlock = createDataBlock(this.sequence++);
      this.dataBlocks.add(this.writeBlock);
    }
    this.length += data.length;
    this.size += 1;
    this.writeBlock.write(data);
  }

  public byte[] read()
    throws IOException
  {
    byte[] result = null;
    if (this.readBlock != null) {
      result = this.readBlock.read();
      if (result == null) {
        if (this.readBlock != this.writeBlock) {
          this.readBlock.close();
          this.dataBlocks.remove(this.readBlock);
          this.readBlock = ((FileDataBlock)this.dataBlocks.get(0));
        }
      }
      else {
        this.length -= result.length;
        this.size -= 1;
      }
    }
    return result;
  }

  public void close()
    throws IOException
  {
    for (int i = 0; i < this.dataBlocks.size(); i++) {
      FileDataBlock db = (FileDataBlock)this.dataBlocks.get(i);
      db.close();
    }
    this.dataBlocks.clear();
    this.readBlock = null;
    this.writeBlock = null;
    this.size = 0;
    this.length = 0L;
  }

  private FileDataBlock createDataBlock(int sequence)
    throws IOException
  {
    String fileName = this.name + "_" + sequence + ".fdb";

    File file = File.createTempFile(this.name, ".fdb", this.dir);
    file.deleteOnExit();
    return new FileDataBlock(file, this.maxBlockSize);
  }
}